package com.zhangsheng.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 张晟
 * @version 1.0
 * @date 2022/11/21 16:46
 */
@Configuration
@Slf4j
public class RabbitConfig {

    /**
     * 订单交换机
     */
    public static String orderExchange="order.exchange";

    /**
     * 订单队列
     */
    public static String orderQueue="order.queue";

    /**
     * 订单路由
     */
    public static String orderRoutingKey="order.routingKey";

    /**
     * 死信交换机
     */
    public static String dlxExchange="dlx.exchange";

    /**
     * 死信队列
     */
    public static String dlxQueue="dlx.queue";

    /**
     * 死信路由
     */
    public static String dlxRoutingKey="dlx.routingKey";

    /**
     * 延迟交换机
     */
    public static String delayExchange = "delay.exchange";

    /**
     * 延迟路由
     */
    public static String delayRoutingKey = "delay.routingKey";

    /**
     * 延迟队列
     */
    public static String delayQueue = "delay.queue";

    /**
     * 声明订单交换机
     */
    @Bean
    public Exchange orderExchange(){
        return new DirectExchange(orderExchange,true,false);
    }

    /**
     * 声明订单队列
     */
    @Bean
    public Queue orderQueue() {
        Map<String, Object> arguments = new HashMap<>(2);
        // 绑定我们的死信交换机
        arguments.put("x-dead-letter-exchange", dlxExchange);
        // 绑定我们的路由key
        arguments.put("x-dead-letter-routing-key", dlxRoutingKey);
        return new Queue(orderQueue, true, false, false, arguments);
    }

    /**
     * 绑定订单队列到死信或者延迟交换机
     */
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(orderRoutingKey).noargs();
    }

    /**
     * 声明死信交换机
     */
    @Bean
    public Exchange dlxExchange(){
        return new DirectExchange(dlxExchange,true,false);
    }

    /**
     * 声明死信队列
     */
    @Bean
    public Queue dlxQueue() {
        return new Queue(dlxQueue , true , false, false);
    }

    /**
     * 绑定死信队列到订单交换机
     */
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(dlxRoutingKey).noargs();
    }

    /**
     * 声明延迟交换机
     */
    @Bean
    public CustomExchange delayExchange(){
        Map<String, Object> args = new HashMap<>(2);
        args.put("x-delayed-type", "topic");
        return new CustomExchange (delayExchange ,"x-delayed-message", true, false, args);
    }

    /**
     * 声明延迟队列
     */
    @Bean
    public Queue delayQueue() {
        return new Queue(delayQueue , true , false, false);
    }

    /**
     * 绑定延迟队列到延迟交换机
     */
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(delayRoutingKey).noargs();
    }

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @PostConstruct
    public void rabbitTemplate(){
        rabbitTemplate.setConfirmCallback((correlationData, ack, reason) -> {
            if (ack){
                log.info("消息发送到交换器成功");
            }else {
                log.error("{}:消息发送到交换机失败" , reason);
            }
        });
        rabbitTemplate.setReturnsCallback(returnedMessage -> {
            if (returnedMessage.getMessage() != null) {
                log.info("{}:消息成功路由到队列",returnedMessage.getMessage().getMessageProperties().getMessageId());
            }else{
                log.error("{}:消息未成功路由到队列",returnedMessage.getMessage().getMessageProperties().getMessageId());
            }
        });
    }

}
